/*
 * 文件名:BaseAction.java
 * 创建时间:2009-03-10
 * 版本:1.0
 * 版权所有:杨涛
 */
package com.yangtao.framework.web.struts2;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable;
import com.yangtao.framework.common.Message;
import com.yangtao.framework.common.SystemConstant;
import com.yangtao.framework.service.ServiceLocator;
import com.yangtao.framework.util.Struts2Utils;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.views.jasperreports.JasperReportConstants;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.ParameterizedType;

/**
 * 所有Action的父类, 它是一个抽象类，不能被实例化，子类必须实现getModel方法
 *
 * @param <M> 扩展类对应的Model类
 * @param <S> 扩展类对应的服务接口类
 * @author 杨涛
 * @date:2009-03-10
 * @修改者:
 * @修改时间:
 * @修改原因:
 * @版本:1.0
 */
public abstract class BaseAction<M extends BaseModel, S> extends ActionSupport
		implements ModelDriven<M>, Preparable {
	/**
	 * 序列化Id
	 */
	private static final long serialVersionUID = 1L;
	/**
	 * 通用返回结果
	 */
	protected static final String COMMON = "common";
	/**
	 * request对象
	 */
	protected HttpServletRequest request = ServletActionContext.getRequest();
	/**
	 * response对象
	 */
	protected HttpServletResponse response = ServletActionContext.getResponse();
	/**
	 * 取得扩展类的服务接口
	 */
	protected S service;
	protected M model;
	/**
	 * 目标视图
	 */
	private String target;
	/**
	 * 报表类型
	 */
	private String reportFormat;

	/**
	 * 构造方法，根据泛型指向的类名实例化该类
	 */
	@SuppressWarnings("unchecked")
	public BaseAction() {
		Class<S> s = (Class<S>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[1];
		this.service = (S) ServiceLocator.getInstance().getService(s);
		Class<M> m = (Class<M>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
		try {
			this.model = m.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// ========================================
	// 公用的CRUD方法
	// ========================================

	/**
	 * 默认的处理方法
	 */
	public String execute() throws Exception {
		return COMMON;
	}

	@Override
	public void prepare() throws Exception {
	}

	/**
	 * 检查是否有执行错误
	 *
	 * @return
	 */
	protected boolean hasError() {
		if (model.getMessage() == null)
			return false;
		for (Message msg : model.getMessage()) {
			if (msg.getType() == SystemConstant.ERROR)
				return true;
		}
		return false;
	}
	protected void processErr(){

	}

	/**
	 * 将消息key格式化为消息字符串
	 */
	protected void formatMessage() {
		if (model.getMessage() == null)
			return;
		for (Message msg : model.getMessage()) {
			msg.setText(getText(msg.getKey(), msg.getArgs()));
		}
	}

	/**
	 * 打印出错消息
	 */
	protected void responseErr() {
		if (model.getMessage() == null)
			return;
		StringBuilder sb = new StringBuilder();
		for (Message msg : model.getMessage()) {
			if (msg.getType() == SystemConstant.ERROR) {
				sb.append(msg.getText());
				sb.append("\n");
			}
		}
		Struts2Utils.renderText(sb.toString());
	}

	/**
	 * 设定目标视图，返回一个通用结果，该通用结果包含一个target的参数
	 *
	 * @param target 目标视图
	 * @return 通用配置的结果
	 */
	public String render(String target) {
		request.setAttribute("pageId", target);
		setTarget(target);
		return COMMON;
	}

	/**
	 * 将对象转换为json返回
	 *
	 * @param object 目标对象
	 * @return
	 */
	public String renderJson(Object object) {
		Struts2Utils.renderJson(object);
		return null;
	}

	/**
	 * 将对象转换为json返回
	 *
	 * @param jsonStr json字符串
	 * @return
	 */
	public String renderJsonString(String jsonStr) {
		Struts2Utils.render("application/json", jsonStr);
		return null;
	}

	/**
	 * 从线程中取出消息，并且实例化为国际化的消息，然后再以json的格式返回
	 *
	 * @return
	 */
	public String renderJsonMessage() {
		formatMessage();
		return renderJson(model.getMessage());
	}

	/**
	 * 返回报表的结果类型
	 *
	 * @param target     报表文件位置
	 * @param reportType 报表类型
	 * @return 报表文件对应的视图名称
	 */
	public String renderJasper(String target, String reportType) {
		setTarget(target);
		setReportFormat(reportType);
		return "jasper";
	}

	/**
	 * 返回报表的结果类型
	 *
	 * @param target 报表文件位置
	 * @return 报表文件对应的视图名称
	 */
	public String renderJasper(String target) {
		return renderJasper(target, JasperReportConstants.FORMAT_PDF);
	}

	/**
	 * @return 目标视图
	 */
	public String getTarget() {
		return target;
	}

	/**
	 * @param target 设定目标视图 默认目标视图在本包下
	 */
	public final void setTarget(String target) {
		this.target = target;
	}

	/**
	 * @return the 报表类型
	 */
	public String getReportFormat() {
		return reportFormat;
	}

	/**
	 * 设置报表类型
	 *
	 * @param reportFormat 报表类型
	 */
	public void setReportFormat(String reportFormat) {
		this.reportFormat = reportFormat;
	}

	public String getPath() {
		// 简单路径
		return ServletActionContext.getRequest().getContextPath();
	}

	/**
	 * 返回模型
	 */
	public final M getModel() {
		return model;
	}
}
